/*******************************************************************
 * author   :  Charlies-ls
 * Date     :  2021-09-26
 * Copyright (c) 2021. artestplay@outlook.com. All Rights Reserved.
 *******************************************************************/
#include "ax_list.h"
#include "com.h"
#include "ax_printf.h"

ax_list* ax_list_create()
{
    ax_list* l = ALLOC(ax_list);
    l->head=0;
    l->tail=0;
    l->count=0;
    return l;
}
void ax_list_destory(ax_list*l)
{
    ax_list_node* node;
    ax_list_foreach2(l,node)
    {
        if(node)
        {
           ax_list_node* next = node->next;
           free(node);
           node = next;
        }
    }
    free(l);
}
void ax_list_destory_all(ax_list*l)
{
    ax_list_node* node;
    printf("list %p \n",l);
    ax_list_foreach2(l,node)
    {
        if(node)
        {
            ax_list_node* next = node->next;
            printf("l: %p %p %p\n",l,node,node->data);
            if(node->data)
                free(node->data);
            free(node);
            node = next;
        }
    }

    free(l);
}

ax_list_node* ax_list_push_back(ax_list*list,ax_list_node* node)
{
    if(NULL == list || NULL == node)
    {
        ax_printf(AX_PERROR,"%s list==NULL or node==NULL!\n",__FUNCTION__);
        return NULL;
    }
    if(NULL == list->head)
    {
        list->head = node;
        list->tail = node;
        node->prev = NULL;
        node->next = NULL;
        list->count++;
    }
    else
    {
        ax_list_insert_after(list, list->tail, node);
    }
    return node;
}

ax_list_node* ax_list_push_back_data(ax_list* list, void* data)
{
    if(NULL == list|| NULL == data)
    {
        ax_printf(AX_PERROR,"%s list==NULL or node==NULL!\n",__FUNCTION__);
        return NULL;
    }
    ax_list_node* node = ALLOC(ax_list_node);
    node->data         = data;
    ax_list_push_back(list,node);
    return node;
}

ax_list_node* ax_list_del(ax_list*list,ax_list_node*node)
{
    ax_check_and_return_zero(list && node && list->count>0, "error");
    if(list->head == node)
    {
        if(list->head->next)
        {
            list->head       = list->head->next;
            list->head->prev = 0;
        }
        else
        {
            list->head = NULL;
            list->tail = NULL;
        }
    }
    else
    {
        if(node == list->tail)
        {
            list->tail = node->prev;
        }
        node->prev->next = node->next;
        if(node->next)
            node->next->prev = node->prev;
    }
    list->count--;
    return node;
}

ax_list_node* ax_list_del_data(ax_list* list,void* data)
{
    ax_check_and_return_zero(list && data, "error");
    ax_list_node* node;
    ax_list_foreach(list,node)
    {
        if(data == node->data)
        {
            return ax_list_del(list, node);
        }
    }
    return NULL;
}
ax_list_node* ax_list_del_front(ax_list*list)
{
    ax_check_and_return_zero(list && list->count > 0, "error");
    return ax_list_del(list,list->head);
}

ax_list_node* ax_list_del_back(ax_list*list)
{
    ax_check_and_return_zero(list && list->count > 0, "error");
    return ax_list_del(list,list->tail);
}

ax_list_node* ax_list_insert_after(ax_list*list,ax_list_node* node_before,ax_list_node*node)
{
    ax_check_and_return_zero(list && node_before && node, "error");
    if(node_before->next)
    {
        node_before->next->prev=node;
        node->next=node_before->next;
    }
    else
        node->next=0;
    node_before->next=node;
    node->prev=node_before;

    if(node_before==list->tail)
        list->tail=node;
    list->count++;
    return node;
}

ax_list_node* ax_list_insert_data_after(ax_list*list,ax_list_node* node_before,void*data)
{
    ax_check_and_return_zero(list && node_before && data, "error");
    ax_list_node* node = ALLOC(ax_list_node);
    node->data=data;
    return ax_list_insert_after(list,node_before,node);
}




ax_list_node* ax_list_push_front(ax_list*list,ax_list_node* node)
{
    ax_check_and_return_zero(list && node, "error");
    if(list->head==0)
    {
        list->head=node;
        list->tail=node;
        node->prev=0;
        node->next=0;
    }
    else
    {
        ax_list_insert_before(list,list->head,node);
    }
    return node;
}
ax_list_node* ax_list_add_push_front_data(ax_list*list,void* data)
{
    ax_check_and_return_zero(list && data, "error");
    ax_list_node* node = ALLOC(ax_list_node);
    node->data         = data;
    return ax_list_push_front(list,node);
}
ax_list_node* ax_list_insert_before(ax_list*list,ax_list_node* node_after,ax_list_node*node)
{
    ax_check_and_return_zero(list && node_after && node, "error");
    if(node_after->prev)
    {
        node_after->prev->next=node;
    }
    node->next       = node_after;
    node->prev       = node_after->prev;
    node_after->prev = node;
    if(node_after == list->head)
        list->head = node;
    list->count++;
    return node;
}
ax_list_node* ax_list_insert_data_before(ax_list*list,ax_list_node* node_after,void*data)
{
    ax_check_and_return_zero(list && node_after && data, "error");
    ax_list_node* node = ALLOC(ax_list_node);
    node->data         = data;
    return ax_list_insert_before(list,node_after,node);
}

int ax_list_size(ax_list* list)
{
    ax_check_and_return_zero(list, "error");
    return list->count;
}


ax_list_node* ax_list_front(ax_list*list)
{
    ax_check_and_return_zero(list, "error");
    return list->head;
}

ax_list_node *ax_list_back(ax_list *list)
{
    ax_check_and_return_zero(list, "error");
    return list->tail;
}

void ax_list_clear(ax_list* l)
{
    ax_check_and_return(l, "error");
    ax_list_foreach2(l,node)
    {
        if(node)
        {
            ax_list_node* next = node->next;
            free(node);
            node = next;
        }
    }
    l->head=0;
    l->tail=0;
    l->count=0;
}
